<?php

namespace App\Macros;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

class ModelTree implements Macro
{
    protected $builder;
    protected $parent_key;
    protected $primary_key;

    public static function inject()
    {
        Builder::macro('tree', function ($parent_id=0, $parent_key='parent_id'){
            return with(new ModelTree($this, $parent_key))->execute($parent_id);
        });
    }

    public function __construct(Builder $builder, $parent_key)
    {
        $this->builder = $builder;
        $this->parent_key = $parent_key;
        $this->primary_key = $this->builder->getModel()->getKeyName();
    }

    public function execute($parent_id=0)
    {
        $items = $this->builder->get();
        $tree = $this->build($items, $parent_id);

        return $tree;
    }

    protected function build(Collection $items, $parent_id)
    {
        $tree = collect();
        $collect = collect();
        $items->map(function($item) use($parent_id, $tree, $collect) {
           if ($item->{$this->parent_key} == $parent_id) {
               $tree->push($item);
           } else {
               $collect->push($item);
           }
        });

        if ($tree->count() > 0 && $items->count()>0) {
            $tree = $tree->map(function($item ) use($collect){
                $children = $this->build($collect, $item->{$this->primary_key});
                if ($children->count()>0) $item->children = $children;
                return $item;
            });
        }

        return $tree;
    }
}
